# 导⼊FastAPI框架和HTTP异常处理模块
from fastapi import FastAPI, HTTPException
# 导⼊Pydantic的基模型，⽤于数据验证和序列化
from pydantic import BaseModel
# 导⼊SQLAlchemy的相关模块，⽤于数据库操作
from sqlalchemy import create_engine, Column, Integer, String
# 导入SQLAlchemy ORM模块中的sessionmaker和declarative_base
# sessionmaker: 用于创建数据库会话工厂，可以配置数据库连接参数，返回Session类用于数据库交互
# declarative_base: 用于创建ORM模型的基类，所有数据库表模型都需要继承自这个基类，提供Python类到数据库表的映射功能
from sqlalchemy.orm import sessionmaker, declarative_base

# 实例化FastAPI对象
app = FastAPI()

# 数据库配置
# 定义数据库的连接URL
DATABASE_URL = "sqlite:///./province.db"
# 创建数据库引擎，设置连接参数以允许在多线程环境中使⽤
# 参数说明:
#  DATABASE_URL: 数据库连接URL字符串，指定要连接的数据库类型和位置
#  connect_args: 连接参数字典，包含额外的数据库连接配置
#  {"check_same_thread": False}: 允许在不同线程中使用同一个数据库连接，主要用于SQLite数据库以支持多线程访问
# 返回值: engine: SQLAlchemy Engine对象，用于执行数据库操作
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})

# 创建一个会话工厂类，用于生成数据库会话对象
# bind: 数据库引擎对象，用于连接具体的数据库
# autocommit: 是否自动提交事务，默认为False表示需要手动提交
# autoflush: 是否自动刷新变更到数据库，默认为False表示需要手动刷新
# 返回值: Session类，可用于创建数据库会话实例
Session = sessionmaker(bind=engine, autocommit=False, autoflush=False)

# 创建⼀个基类，⽤于后续定义数据库表模型
Base = declarative_base()


# 定义数据库表模型
class Province(Base):
    """
    定义数据库表模型，映射到数据库中的province表
    该类用于表示省份信息，包含省份的唯一标识、名称和编码

    属性:
        id (Integer): 省份的主键ID，自动递增，用于唯一标识每条记录
        name (String): 省份名称，最大长度50个字符，不允许为空且必须唯一
        code (String): 省份编码，最大长度10个字符，不允许为空且必须唯一
    """
    __tablename__ = "province"  # 表名
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50), unique=True, nullable=False)
    code = Column(String(10), unique=True, nullable=False)


# 创建数据库表
Base.metadata.create_all(bind=engine)


# 请求与响应数据的校验
class ProvinceCreate(BaseModel):
    """
    省份创建数据模型类
    用于定义创建省份时需要提供的数据结构，包含省份名称和编码信息
    属性:
        name (str): 省份名称
        code (str): 省份编码
    """
    name: str
    code: str


class ProvinceUpdate(BaseModel):
    """
    省份更新数据模型类
    用于定义更新省份信息时需要提供的数据结构，包含省份名称和编码信息
    属性:
        name (str): 省份名称
        code (str): 省份编码
    """
    name: str
    code: str


class ProvinceResponse(BaseModel):
    """
    省份响应数据模型类
    用于定义返回省份信息数据结构，包含省份的唯一标识、名称和编码
    属性:
        id (int): 省份唯一标识符
        name (str): 省份名称
        code (str): 省份编码
    """
    id: int
    name: str
    code: str


# API路由接口实现
# 1.创建省份
@app.post("/provinces/", response_model=ProvinceResponse)
def create_province(pv: ProvinceCreate):
    # 创建数据库会话
    DB = Session()
    #   异常处理
    # 异常处理: 检测省份名称是否已存在
    try:
        existing_province = DB.query(Province).filter(Province.name == pv.name).first()
        if existing_province:
            raise HTTPException(status_code=400, detail="省份已存在")
        else:
            # 插⼊新省份
            new_province = Province(name=pv.name, code=pv.code)
            DB.add(new_province)  # 添加
            DB.commit()  # 提交
            DB.refresh(new_province)  # 刷新
            return new_province

    except:
        DB.rollback()  # 回滚
    finally:
        DB.close()  # 关闭会话


class ProvinceResponse(BaseModel):
    """
    省份响应数据模型类
    用于定义返回省份信息的数据结构，包含省份的唯一标识、名称和编码
    属性:
        id (int): 省份唯一标识符
        name (str): 省份名称
        code (str): 省份编码
    """
    id: int
    name: str
    code: str


# 创建fastAPI路由接口
@app.get("/provinces/")
def get_all_provinces():
    """
    查询所有省份信息。
    :return:
    """
    print("查询所有省份信息")


if __name__ == '__main__':
    import uvicorn

    uvicorn.run(app, host="127.0.0.1", port=8000)
